package com.example.androidautoproject.service

import android.graphics.Rect
import android.text.TextUtils
import android.util.Log
import android.view.accessibility.AccessibilityNodeInfo
import com.ven.assists.AssistsCore.des
import com.ven.assists.AssistsCore.isImageButton
import com.ven.assists.AssistsCore.isImageView
import com.ven.assists.AssistsCore.isTextView

import com.ven.assists.service.AssistsService
import org.json.JSONArray
import org.json.JSONObject



class AssistsToolCore {
    private lateinit var clickArr:JSONArray
    private lateinit var imageArr:JSONArray
    private lateinit var textArr:JSONArray
    fun getNodeTreeAsJson(): JSONObject {
        val rootNode = AssistsService.instance?.rootInActiveWindow
        return rootNode?.let{node ->
            convertNodeToJson(node)
        }?:JSONObject().apply {
            put("error", "No root node available")
        }
    }
    private fun convertNodeToJson(node:AccessibilityNodeInfo):JSONObject{
        val bounds = Rect()
        node.getBoundsInScreen(bounds)
        return JSONObject().apply {
            put("className", node.className?.toString() ?: "Unknown")
            put("text", node.text?.toString() ?: "")
            put("desc", node.des())
            put("resourceName", node.viewIdResourceName ?: "")
            put("id", node.viewIdResourceName ?: System.identityHashCode(node).toString())
            put("bounds", JSONObject().apply {
                put("left", bounds.left)
                put("top", bounds.top)
                put("right", bounds.right)
                put("bottom", bounds.bottom)
            })
            put("clickable", node.isClickable)
            put("isVisibleToUser", node.isVisibleToUser)
            put("longClickable", node.isLongClickable)
            put("scrollable", node.isScrollable)
            put("checkable", node.isCheckable)
            put("checked", node.isChecked)
            put("enabled", node.isEnabled)
            put("focused", node.isFocused)
            put("selected", node.isSelected)

            val children = JSONArray()
            for (i in 0 until node.childCount) {
                node.getChild(i)?.let { child ->
                    children.put(convertNodeToJson(child))
                    child.recycle()
                }
            }
            put("children", children)
        }
    }

    fun getClickNodesAsJson(): JSONArray {
        val rootNode = AssistsService.instance?.rootInActiveWindow
        clickArr = JSONArray()
        rootNode?.let { node ->
            convertClickNodeToJson(node)
        }
        return clickArr
    }
    fun getImageNodesAsJson(): JSONArray {
        val rootNode = AssistsService.instance?.rootInActiveWindow
        imageArr = JSONArray()
        rootNode?.let { node ->
            convertImageNodeToJson(node)
        }
        return imageArr
    }
    fun getTextNodesAsJson(): JSONArray {
        val rootNode = AssistsService.instance?.rootInActiveWindow
        textArr = JSONArray()
        rootNode?.let { node ->
            convertTextNodeToJson(node)
        }
        return textArr
    }
    private fun convertClickNodeToJson(node:AccessibilityNodeInfo){
        val bounds = Rect()
        node.getBoundsInScreen(bounds)
        var jsonObj = JSONObject()
//        Log.e("ServerProject", "node text ${node.text} ${ TextUtils.isEmpty(node.text)}")
        if (node.isClickable &&
            node.isVisibleToUser &&
            (node.isImageView() || node.isImageButton() || (node.isTextView() && TextUtils.isEmpty(node.text))) &&
            (bounds.right - bounds.left) < 200 &&
            (bounds.bottom - bounds.top) < 200){
            jsonObj.put("className", node.className?.toString() ?: "Unknown")
            jsonObj.put("text", node.text?.toString() ?: "")
            jsonObj.put("desc", node.des())
            jsonObj.put("resourceName", node.viewIdResourceName ?: "")
            jsonObj.put("id", node.viewIdResourceName ?: System.identityHashCode(node).toString())
            jsonObj.put("bounds", JSONObject().apply {
                put("left", bounds.left)
                put("top", bounds.top)
                put("right", bounds.right)
                put("bottom", bounds.bottom)
            })
            jsonObj.put("clickable", node.isClickable)
            jsonObj.put("isVisibleToUser", node.isVisibleToUser)
            jsonObj.put("longClickable", node.isLongClickable)
            jsonObj.put("scrollable", node.isScrollable)
            jsonObj.put("checkable", node.isCheckable)
            jsonObj.put("checked", node.isChecked)
            jsonObj.put("enabled", node.isEnabled)
            jsonObj.put("focused", node.isFocused)
            jsonObj.put("selected", node.isSelected)
            clickArr.put(jsonObj)
        }
        for (i in 0 until node.childCount) {
            node.getChild(i)?.let { child ->
                convertClickNodeToJson(child)
                child.recycle()
            }
        }
    }
    private fun convertImageNodeToJson(node:AccessibilityNodeInfo){
        val bounds = Rect()
        node.getBoundsInScreen(bounds)
        var jsonObj = JSONObject()
        if ((node.isImageView() || node.isImageButton() || node.className?.toString()!!.contains("image", ignoreCase = true)) && node.isVisibleToUser){
            jsonObj.put("className", node.className?.toString() ?: "Unknown")
            jsonObj.put("text", node.text?.toString() ?: "")
            jsonObj.put("desc", node.des())
            jsonObj.put("resourceName", node.viewIdResourceName ?: "")
            jsonObj.put("id", node.viewIdResourceName ?: System.identityHashCode(node).toString())
            jsonObj.put("bounds", JSONObject().apply {
                put("left", bounds.left)
                put("top", bounds.top)
                put("right", bounds.right)
                put("bottom", bounds.bottom)
            })
            jsonObj.put("clickable", node.isClickable)
            jsonObj.put("isVisibleToUser", node.isVisibleToUser)
            jsonObj.put("longClickable", node.isLongClickable)
            jsonObj.put("scrollable", node.isScrollable)
            jsonObj.put("checkable", node.isCheckable)
            jsonObj.put("checked", node.isChecked)
            jsonObj.put("enabled", node.isEnabled)
            jsonObj.put("focused", node.isFocused)
            jsonObj.put("selected", node.isSelected)
            imageArr.put(jsonObj)
        }

        for (i in 0 until node.childCount) {
            node.getChild(i)?.let { child ->
                convertImageNodeToJson(child)
                child.recycle()
            }
        }
    }

    private fun convertTextNodeToJson(node:AccessibilityNodeInfo){
        val bounds = Rect()
        node.getBoundsInScreen(bounds)
        var jsonObj = JSONObject()
        if ((node.isTextView()|| node.className?.toString()!!.contains("text", ignoreCase = true)) && node.isVisibleToUser){
            jsonObj.put("className", node.className?.toString() ?: "Unknown")
            jsonObj.put("text", node.text?.toString() ?: "")
            jsonObj.put("desc", node.des())
            jsonObj.put("resourceName", node.viewIdResourceName ?: "")
            jsonObj.put("id", node.viewIdResourceName ?: System.identityHashCode(node).toString())
            jsonObj.put("bounds", JSONObject().apply {
                put("left", bounds.left)
                put("top", bounds.top)
                put("right", bounds.right)
                put("bottom", bounds.bottom)
            })
            jsonObj.put("clickable", node.isClickable)
            jsonObj.put("isVisibleToUser", node.isVisibleToUser)
            jsonObj.put("longClickable", node.isLongClickable)
            jsonObj.put("scrollable", node.isScrollable)
            jsonObj.put("checkable", node.isCheckable)
            jsonObj.put("checked", node.isChecked)
            jsonObj.put("enabled", node.isEnabled)
            jsonObj.put("focused", node.isFocused)
            jsonObj.put("selected", node.isSelected)
            textArr.put(jsonObj)
        }

        for (i in 0 until node.childCount) {
            node.getChild(i)?.let { child ->
                convertTextNodeToJson(child)
                child.recycle()
            }
        }
    }
}